package dooption

import (
	"bytes"
	"encoding/json"
	"gitee.com/jmdvirus/jkgo/jk/jklog"
	"io/ioutil"
	"os/exec"
)

type DebugControlCmds struct {
	CmdBase          string `json:"cmdBase"`
	CmdBaseArg       string `json:"cmdBaseArg"`
	RemoteOpen       string `json:"remoteOpen"`
	RemoteClose      string `json:"remoteClose"`
	RemoteSeeId      string `json:"remoteSeeId"`
	RemoteSeeFile    string `json:"remoteSeeFile"`
	RemoteClear      string `json:"remoteClear"`
	RemoteGetFile    string `json:"remoteGetFile"`
	RemoteClearVoice string `json:"remoteClearVoice"`
	Code             string `json:"code"`
}

type DebugControl struct {
	Id   string
	Cmds DebugControlCmds
}

var sDebugControl DebugControl

func DebugControlGlobal() *DebugControl {
	return &sDebugControl
}

/**
 * 命令行调用使用 /bin/bash -c "xxxx"
 * 具体命令如果一起传入作为整体处理，分开则是输入顺序
 */
func cmdExec(cmdstr string, arg ...string) (string, error) {
	jklog.L().Debugln("cmd ", cmdstr)
	//cmd := exec.Command(cmdstr, arg...)
	//stdout, err := cmd.StdoutPipe()
	//if err != nil { //获取输出对象，可以从该对象中读取输出结果
	//	return "", err
	//}
	//defer stdout.Close()                // 保证关闭输出流
	//if err := cmd.Start(); err != nil { // 运行命令
	//	return "", err
	//}
	//
	//if opBytes, err := ioutil.ReadAll(stdout); err != nil { // 读取输出结果
	//	return "", err
	//} else {
	//	return string(opBytes), err
	//}

	//首先生成cmd结构体,该结构体包含了很多信息，如执行命令的参数，命令的标准输入输出等
	command := exec.Command(cmdstr, arg...)
	//给标准输入以及标准错误初始化一个buffer，每条命令的输出位置可能是不一样的，
	//比如有的命令会将输出放到stdout，有的放到stderr
	command.Stdout = &bytes.Buffer{}
	command.Stderr = &bytes.Buffer{}
	//执行命令，直到命令结束
	err := command.Run()
	if err != nil {
		//打印程序中的错误以及命令行标准错误中的输出
		return command.Stderr.(*bytes.Buffer).String(), err
	}
	//打印命令行的标准输出
	return command.Stdout.(*bytes.Buffer).String(), err
}

func init() {
	d, _ := ioutil.ReadFile("./cmds.json")
	json.Unmarshal(d, &sDebugControl.Cmds)
}

func (dc *DebugControl) DebugControlRemoteOpen(id string) (string, error) {
	cmd := dc.Cmds.RemoteOpen + id
	jklog.L().Debugln("exec with cmd ", cmd)
	d, err := cmdExec(dc.Cmds.CmdBase, dc.Cmds.CmdBaseArg, cmd)
	return d, err
}

func (dc *DebugControl) DebugControlRemoteClose(id string) (string, error) {
	cmd := dc.Cmds.RemoteClose + id
	jklog.L().Debugln("exec with cmd ", cmd)
	return cmdExec(dc.Cmds.CmdBase, dc.Cmds.CmdBaseArg, cmd)
}

func (dc *DebugControl) DebugControlRemoteCall(id string, cmd string) (string, error) {
	jklog.L().Debugln("call cmd ", cmd)
	if cmd == "seeId" {
		return cmdExec(dc.Cmds.CmdBase, dc.Cmds.CmdBaseArg, dc.Cmds.RemoteSeeId)
	} else if cmd == "seeFile" {
		return cmdExec(dc.Cmds.CmdBase, dc.Cmds.CmdBaseArg, dc.Cmds.RemoteSeeFile)
	} else if cmd == "clear" {
		return cmdExec(dc.Cmds.CmdBase, dc.Cmds.CmdBaseArg, dc.Cmds.RemoteClear)
	} else if cmd == "clearVoice" {
		return cmdExec(dc.Cmds.CmdBase, dc.Cmds.CmdBaseArg, dc.Cmds.RemoteClearVoice)
	}
	return "unsupport", nil
}

func (dc *DebugControl) DebugControlRemoteGetFile(id string, filename string) (string, error) {
	jklog.L().Debugln("get file ", filename)
	cmd := dc.Cmds.RemoteGetFile + id + " -f " + "/userdata/log/" + filename
	return cmdExec(dc.Cmds.CmdBase, dc.Cmds.CmdBaseArg, cmd)
}
